<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as d3 from 'd3'

const svg = ref(null)

onMounted(() => {
  window.addEventListener('resize', setTime)
  draw()
})
onUnmounted(() => {
  window.removeEventListener('resize', setTime)
})

const setTime = () => {
  setTimeout(() => {
    draw()
  })
}

const draw = () => {
  // 获取容器元素，并获取宽高
  const box = document.getElementById('main')
  const height = box.clientHeight
  const width = box.clientWidth
  const margin = {
    top: 40,
    bottom: 40,
    left: 60,
    right: 40
  }
  // 渲染的数据
  const data = [
    { name: 'Mon', age: 120 },
    { name: 'Tue', age: 200 },
    { name: 'Wed', age: 150 },
    { name: 'Thu', age: 80 },
    { name: 'Fri', age: 70 },
    { name: 'Sat', age: 110 },
    { name: 'Sun', age: 130 }
  ]

  if (!svg.value) {
    // 创建容器
    svg.value = d3
      .select('#main')
      .append('svg')
      .attr('height', height - 10)
      .attr('width', width)
      .attr('viewBox', [0, 0, width, height - 10])
  } else {
    // 使用容器
    svg.value
      .attr('width', width)
      .attr('height', height - 10)
      .attr('viewBox', [0, 0, width, height - 10])
    // 绘制前清空
    svg.value.selectAll('*').remove()
  }
  // 创建X轴
  const x = d3
    .scaleBand()
    .domain(d3.range(data.length))
    .range([margin.left, width - margin.right])
    .paddingInner(0.3)
    .paddingOuter(0.3)

  // Y轴最大值
  const ymax = d3.max(data, d => d.age)
  // 创建Y轴
  const y = d3
    .scaleLinear()
    .domain([0, ymax])
    .range([height - margin.bottom, margin.top])

  // 绘制X轴
  svg.value.append('g').call(g => {
    g.attr('transform', `translate(0, ${height - margin.bottom})`)
      .call(d3.axisBottom(x).tickFormat(i => data[i].name))
      .attr('font-size', 20)
      .attr('color', '#6E7079')
  })

  // 绘制Y轴
  svg.value.append('g').call(g => {
    const yz = g
      .attr('transform', `translate(${margin.left}, 0)`)
      .call(
        d3
          .axisLeft(y)
          .ticks(4)
          .tickSize(margin.right + margin.left - width)
      )
      .attr('font-size', 20)
    // 隐藏左侧竖线
    yz.selectAll('path').attr('color', 'transparent')
    // 修改横线颜色
    yz.selectAll('line').attr('stroke', '#E0E6F1')
    // 修改文字颜色
    yz.selectAll('text').attr('fill', '#6E7079')
  })

  // 创建柱状图阴影
  svg.value
    .append('g')
    .attr('fill', '#b4b4b4')
    .attr('fill-opacity', 0.2)
    .selectAll('.back')
    .data(data)
    .join('rect')
    .attr('class', 'back')
    .attr('x', (_d, i) => x(i))
    .attr('y', y(ymax))
    .attr('height', y(0) - margin.top)
    .attr('width', x.bandwidth())

  // 创建柱状图
  svg.value
    .append('g')
    .attr('fill', '#5470c6')
    .selectAll('.pillar')
    .data(data)
    .join('rect')
    .attr('id', d => 'rect_' + d.name)
    .attr('class', 'pillar')
    .attr('x', (_d, i) => x(i))
    .attr('y', d => y(d.age))
    .attr('height', d => y(0) - y(d.age))
    .attr('width', x.bandwidth())
    .attr('cursor', 'pointer')
    .on('mouseover', d => {
      if (d.target.id) {
        d3.select('#' + d.target.id).attr('fill', '#5c7bd9')
      }
    })
    .on('mouseout', d => {
      if (d.target.id) {
        d3.select('#' + d.target.id).attr('fill', '#5470c6')
      }
    })

  // 整体绘制
  svg.value.node()
}
</script>

<template>
  <div class="bar-background">
    <div class="header">
      <h1>带背景色的柱状图</h1>
    </div>
    <div id="main" class="main"></div>
  </div>
</template>

<style lang="scss" scoped>
.bar-background {
  position: relative;
  height: 100%;
  width: 100%;
  .header {
    margin-left: 20px;
    line-height: 60px;
  }
  .main {
    position: absolute;
    top: 60px;
    bottom: 0;
    left: 0;
    right: 0;
  }
}
</style>
